package com.example.service;

import com.example.entity.Document;
import com.example.entity.DocumentVersion;
import com.example.entity.EditSession;
import com.example.entity.DocumentDraft;
import com.example.mapper.DocumentMapper;
import com.example.mapper.DocumentVersionMapper;
import com.example.mapper.EditSessionMapper;
import com.example.mapper.DocumentDraftMapper;
import com.example.mapper.KnowledgeSpaceMapper;
import com.example.exception.BusinessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;

@Service
public class DocumentService {

    private static final Logger logger = LoggerFactory.getLogger(DocumentService.class);

    @Autowired
    private DocumentMapper documentMapper;

    @Autowired
    private DocumentVersionMapper documentVersionMapper;

    @Autowired
    private EditSessionMapper editSessionMapper;

    @Autowired
    private DocumentDraftMapper documentDraftMapper;

    @Autowired
    private KnowledgeSpaceMapper knowledgeSpaceMapper;

    @Autowired
    private MarkdownService markdownService;

    @Value("${file.upload.path:uploads/documents}")
    private String uploadPath;

    /**
     * 根据空间ID获取文档列表
     */
    public List<Document> getDocumentsBySpaceId(Integer spaceId) {
        if (spaceId == null || spaceId <= 0) {
            throw new BusinessException.ValidationException("空间ID不能为空且必须大于0");
        }

        try {
            List<Document> documents = documentMapper.getDocumentsBySpaceId(spaceId);
            logger.debug("获取空间{}的文档成功，共{}个", spaceId, documents.size());
            return documents;
        } catch (Exception e) {
            logger.error("获取空间文档失败: {}", e.getMessage(), e);
            throw new BusinessException("获取空间文档失败", e);
        }
    }

    /**
     * 根据文档ID获取文档详情
     */
    public Document getDocumentById(Integer documentId) {
        if (documentId == null || documentId <= 0) {
            throw new BusinessException.ValidationException("文档ID不能为空且必须大于0");
        }

        try {
            Document document = documentMapper.getDocumentById(documentId);
            if (document == null) {
                throw new BusinessException.DataNotFoundException("文档不存在");
            }

            // 如果是文件系统存储，需要读取文件内容
            if ("filesystem".equals(document.getStorageType()) && document.getFilePath() != null) {
                try {
                    String content = readFileContent(document.getFilePath());
                    document.setContent(content);
                } catch (Exception e) {
                    // 文件读取失败时，记录日志但不影响其他信息的返回
                    logger.error("读取文件内容失败: {}, 错误: {}", document.getFilePath(), e.getMessage(), e);
                    document.setContent("文件内容读取失败: " + e.getMessage());
                }
            }

            return document;
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            logger.error("获取文档详情失败: {}", e.getMessage(), e);
            throw new BusinessException("获取文档详情失败", e);
        }
    }

    /**
     * 创建新文档
     */
    @Transactional(rollbackFor = Exception.class)
    public int createDocument(Document document) {
        validateDocument(document);

        try {
            // 检查文档名称是否已存在
            if (isDocumentNameExists(document.getDocumentName(), document.getSpaceId())) {
                throw new BusinessException.DuplicateDataException("该空间中已存在同名文档");
            }

            document.setCreatedAt(LocalDateTime.now());
            document.setUpdatedAt(LocalDateTime.now());

            // 只为新建文档（非上传文件）设置默认属性
            if (document.getStorageType() == null) {
                // 新建文档（txt/md格式）存储在数据库中
                document.setStorageType("database");
                document.setFileSize(document.getContent() != null ? (long) document.getContent().length() : 0L);
                document.setDownloadCount(0);
                document.setVersion(1);
                document.setIsDeleted(false);
                document.setIsLocked(false);
                document.setAutoSaveEnabled(true);

                // 根据文档类型设置文件扩展名和MIME类型
                if ("markdown".equals(document.getDocumentType())) {
                    document.setFileExtension(".md");
                    document.setMimeType("text/markdown");
                } else if ("text".equals(document.getDocumentType())) {
                    document.setFileExtension(".txt");
                    document.setMimeType("text/plain");
                }

                // 设置原始文件名（基于文档名称）
                if (document.getOriginalFilename() == null) {
                    document.setOriginalFilename(document.getDocumentName() + document.getFileExtension());
                }
            }

            int result = documentMapper.insertDocument(document);

            // 更新空间文档数量
            if (result > 0) {
                updateSpaceDocumentCount(document.getSpaceId());
                logger.info("文档创建成功: {}", document.getDocumentName());
            }

            return result;
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            logger.error("创建文档失败: {}", e.getMessage(), e);
            throw new BusinessException("创建文档失败", e);
        }
    }

    /**
     * 更新文档信息
     */
    @Transactional(rollbackFor = Exception.class)
    public int updateDocument(Document document) {
        validateDocument(document);

        if (document.getDocumentId() == null || document.getDocumentId() <= 0) {
            throw new BusinessException.ValidationException("文档ID不能为空且必须大于0");
        }

        try {
            // 检查文档是否存在
            Document existingDocument = documentMapper.getDocumentById(document.getDocumentId());
            if (existingDocument == null) {
                throw new BusinessException.DataNotFoundException("要更新的文档不存在");
            }

            // 检查文档名称是否与其他文档冲突
            Document duplicateDoc = documentMapper.getDocumentByNameAndSpace(document.getDocumentName(), document.getSpaceId());
            if (duplicateDoc != null && !duplicateDoc.getDocumentId().equals(document.getDocumentId())) {
                throw new BusinessException.DuplicateDataException("该空间中已存在同名文档");
            }

            document.setUpdatedAt(LocalDateTime.now());
            int result = documentMapper.updateDocument(document);

            if (result > 0) {
                logger.info("文档更新成功: {}", document.getDocumentName());
            }

            return result;
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            logger.error("更新文档失败: {}", e.getMessage(), e);
            throw new BusinessException("更新文档失败", e);
        }
    }

    /**
     * 删除文档
     */
    @Transactional(rollbackFor = Exception.class)
    public int deleteDocument(Integer documentId) {
        if (documentId == null || documentId <= 0) {
            throw new BusinessException.ValidationException("文档ID不能为空且必须大于0");
        }

        try {
            Document document = documentMapper.getDocumentById(documentId);
            if (document == null) {
                throw new BusinessException.DataNotFoundException("要删除的文档不存在");
            }

            int result = documentMapper.deleteDocument(documentId);

            // 删除文件系统中的文件
            if (result > 0 && "filesystem".equals(document.getStorageType())
                    && document.getFilePath() != null) {
                deleteFileFromSystem(document.getFilePath());
            }

            // 更新空间文档数量
            if (result > 0) {
                updateSpaceDocumentCount(document.getSpaceId());
                logger.info("文档删除成功: {}", documentId);
            }

            return result;
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            logger.error("删除文档失败: {}", e.getMessage(), e);
            throw new BusinessException("删除文档失败", e);
        }
    }

    /**
     * 检查文档名称是否在空间中已存在
     */
    public boolean isDocumentNameExists(String documentName, Integer spaceId) {
        Document existingDoc = documentMapper.getDocumentByNameAndSpace(documentName, spaceId);
        return existingDoc != null;
    }

    /**
     * 获取用户收藏的文档列表
     */
    public List<Document> getFavoriteDocuments(String username) {
        if (username == null || username.trim().isEmpty()) {
            throw new BusinessException.ValidationException("用户名不能为空");
        }

        try {
            List<Document> documents = documentMapper.getFavoriteDocuments(username);
            logger.debug("获取用户{}的收藏文档成功，共{}个", username, documents.size());
            return documents;
        } catch (Exception e) {
            logger.error("获取收藏文档失败: {}", e.getMessage(), e);
            throw new BusinessException("获取收藏文档失败", e);
        }
    }

    /**
     * 添加文档收藏
     */
    public int addDocumentFavorite(Integer documentId, String username) {
        return documentMapper.addDocumentFavorite(documentId, username);
    }

    /**
     * 取消文档收藏
     */
    public int removeDocumentFavorite(Integer documentId, String username) {
        return documentMapper.removeDocumentFavorite(documentId, username);
    }

    /**
     * 记录文档访问历史
     */
    public int recordDocumentAccess(Integer documentId, String username) {
        return documentMapper.insertAccessHistory(documentId, username);
    }

    /**
     * 获取用户最近访问的文档
     */
    public List<Document> getRecentDocuments(String username, Integer limit) {
        if (username == null || username.trim().isEmpty()) {
            throw new BusinessException.ValidationException("用户名不能为空");
        }

        if (limit == null || limit <= 0) {
            limit = 10; // 默认返回10条
        }

        try {
            List<Document> documents = documentMapper.getRecentDocuments(username, limit);
            logger.debug("获取用户{}的最近文档成功，共{}个", username, documents.size());
            return documents;
        } catch (Exception e) {
            logger.error("获取最近文档失败: {}", e.getMessage(), e);
            throw new BusinessException("获取最近文档失败", e);
        }
    }

    /**
     * 更新空间的文档数量
     */
    private void updateSpaceDocumentCount(Integer spaceId) {
        try {
            List<Document> documents = documentMapper.getDocumentsBySpaceId(spaceId);
            int count = documents != null ? documents.size() : 0;
            knowledgeSpaceMapper.updateDocumentCount(spaceId, count);
            logger.debug("更新空间{}文档数量为{}", spaceId, count);
        } catch (Exception e) {
            logger.error("更新空间文档数量失败: {}", e.getMessage(), e);
            // 这里不抛出异常，避免影响主要业务流程
        }
    }

    private void validateDocument(Document document) {
        if (document == null) {
            throw new BusinessException.ValidationException("文档信息不能为空");
        }
        if (document.getDocumentName() == null || document.getDocumentName().trim().isEmpty()) {
            throw new BusinessException.ValidationException("文档名称不能为空");
        }
        if (document.getSpaceId() == null || document.getSpaceId() <= 0) {
            throw new BusinessException.ValidationException("空间ID不能为空且必须大于0");
        }
        if (document.getDocumentName().length() > 100) {
            throw new BusinessException.ValidationException("文档名称长度不能超过100个字符");
        }
    }

    // ========== 在线编辑功能 ==========

    /**
     * 开始编辑文档
     */
    @Transactional
    public String startEditSession(Integer documentId, String username) {
        // 检查文档是否被其他用户锁定
        EditSession existingSession = editSessionMapper.getActiveSessionByDocumentIdAndNotUser(documentId, username);
        if (existingSession != null) {
            throw new RuntimeException("文档正在被用户 " + existingSession.getEditorUsername() + " 编辑中");
        }

        // 创建新的编辑会话
        String sessionId = UUID.randomUUID().toString();
        EditSession editSession = new EditSession();
        editSession.setSessionId(sessionId);
        editSession.setDocumentId(documentId);
        editSession.setEditorUsername(username);
        editSession.setIsActive(true);
        editSession.setStartTime(LocalDateTime.now());
        editSession.setLastActivity(LocalDateTime.now());
        editSessionMapper.insertEditSession(editSession);

        // 锁定文档
        Document document = getDocumentById(documentId);
        document.setIsLocked(true);
        document.setLastEditorUsername(username);
        document.setLockExpiresAt(LocalDateTime.now().plusHours(2)); // 2小时后自动解锁
        updateDocument(document);

        return sessionId;
    }

    /**
     * 结束编辑会话
     */
    @Transactional
    public void endEditSession(String sessionId, String username) {
        EditSession editSession = getEditSession(sessionId);
        if (editSession == null || !editSession.getEditorUsername().equals(username)) {
            throw new RuntimeException("无效的编辑会话");
        }

        // 结束编辑会话
        editSessionMapper.endEditSession(sessionId);

        // 解锁文档
        Document document = getDocumentById(editSession.getDocumentId());
        document.setIsLocked(false);
        document.setLockExpiresAt(null);
        updateDocument(document);

        // 删除相关草稿
        documentDraftMapper.deleteDraftsByDocumentId(editSession.getDocumentId());
    }

    /**
     * 保存文档并创建版本
     */
    @Transactional
    public int saveDocumentWithVersion(Integer documentId, String content, String username, String editSummary) {
        // 验证Markdown语法（如果是Markdown文档）
        Document document = getDocumentById(documentId);
        if (document.getOriginalFilename() != null && document.getOriginalFilename().endsWith(".md")) {
            if (!markdownService.isValidMarkdown(content)) {
                throw new RuntimeException("Markdown语法错误");
            }
        }

        // 创建新版本记录
        DocumentVersion version = new DocumentVersion();
        version.setDocumentId(documentId);
        version.setVersionNumber(getMaxVersionNumber(documentId) + 1);
        version.setContent(content);
        version.setEditorUsername(username);
        version.setEditSummary(editSummary != null ? editSummary : "文档更新");
        version.setContentSize(content.length());
        version.setCreatedAt(LocalDateTime.now());
        documentVersionMapper.insertDocumentVersion(version);

        // 更新文档内容
        document.setContent(content);
        document.setLastEditorUsername(username);
        document.setFileSize((long) content.length());
        return updateDocument(document);
    }

    /**
     * 自动保存草稿
     */
    public void autoSaveDraft(Integer documentId, String content, String username, String sessionId) {
        // 检查是否已存在草稿
        DocumentDraft existingDraft = documentDraftMapper.getDraftByDocumentIdAndUser(documentId, username);

        if (existingDraft != null) {
            // 更新现有草稿
            existingDraft.setDraftContent(content);
            existingDraft.setAutoSaveTime(LocalDateTime.now());
            documentDraftMapper.insertOrUpdateDraft(existingDraft);
        } else {
            // 创建新草稿
            DocumentDraft draft = new DocumentDraft();
            draft.setDocumentId(documentId);
            draft.setEditorUsername(username);
            draft.setDraftContent(content);
            draft.setAutoSaveTime(LocalDateTime.now());
            documentDraftMapper.insertOrUpdateDraft(draft);
        }

        // 更新编辑会话的最后活动时间
        editSessionMapper.updateLastActivity(sessionId);
    }

    /**
     * 获取文档的版本历史
     */
    public List<DocumentVersion> getDocumentVersions(Integer documentId) {
        return documentVersionMapper.getVersionsByDocumentId(documentId);
    }

    /**
     * 获取文档的最大版本号
     */
    private Integer getMaxVersionNumber(Integer documentId) {
        Integer maxVersion = documentVersionMapper.getMaxVersionNumber(documentId);
        return maxVersion != null ? maxVersion : 0;
    }

    /**
     * 获取编辑会话
     */
    private EditSession getEditSession(String sessionId) {
        return editSessionMapper.getSessionById(sessionId);
    }

    // ========== Markdown处理功能 ==========

    /**
     * 将Markdown文档转换为HTML预览
     */
    public String getMarkdownPreview(Integer documentId) {
        Document document = documentMapper.getDocumentById(documentId);
        if (document == null) {
            throw new RuntimeException("文档不存在");
        }

        if ("md".equals(document.getFileExtension()) || "markdown".equals(document.getDocumentType())) {
            return markdownService.markdownToHtml(document.getContent());
        }

        return document.getContent(); // 非Markdown文档直接返回内容
    }

    /**
     * 生成Markdown文档目录
     */
    public String generateMarkdownToc(Integer documentId) {
        Document document = documentMapper.getDocumentById(documentId);
        if (document == null) {
            throw new RuntimeException("文档不存在");
        }

        if ("md".equals(document.getFileExtension()) || "markdown".equals(document.getDocumentType())) {
            return markdownService.generateToc(document.getContent());
        }

        return ""; // 非Markdown文档返回空字符串
    }

    /**
     * 提取Markdown文档中的图片和链接
     */
    public DocumentResourceInfo extractMarkdownResources(Integer documentId) {
        Document document = documentMapper.getDocumentById(documentId);
        if (document == null) {
            throw new RuntimeException("文档不存在");
        }

        DocumentResourceInfo resourceInfo = new DocumentResourceInfo();

        if ("md".equals(document.getFileExtension()) || "markdown".equals(document.getDocumentType())) {
            resourceInfo.setImageUrls(markdownService.extractImageUrls(document.getContent()));
            resourceInfo.setLinks(markdownService.extractLinks(document.getContent()));
        }

        return resourceInfo;
    }

    /**
     * 文档资源信息类
     */
    public static class DocumentResourceInfo {
        private List<String> imageUrls;
        private List<String> links;

        public List<String> getImageUrls() {
            return imageUrls;
        }

        public void setImageUrls(List<String> imageUrls) {
            this.imageUrls = imageUrls;
        }

        public List<String> getLinks() {
            return links;
        }

        public void setLinks(List<String> links) {
            this.links = links;
        }
    }

    /**
     * 根据关键词搜索文档
     */
    public List<Document> searchDocumentsByKeyword(String keyword, Integer spaceId) {
        if (keyword == null || keyword.trim().isEmpty()) {
            return getDocumentsBySpaceId(spaceId);
        }
        return documentMapper.searchDocumentsByKeyword(keyword.trim(), spaceId);
    }

    /**
     * 根据文档标题搜索
     */
    public List<Document> searchDocumentsByTitle(String title, Integer spaceId) {
        return documentMapper.searchDocumentsByTitle(title, spaceId);
    }

    /**
     * 根据文档内容搜索
     */
    public List<Document> searchDocumentsByContent(String content, Integer spaceId) {
        return documentMapper.searchDocumentsByContent(content, spaceId);
    }

    /**
     * 根据创建者搜索文档
     */
    public List<Document> searchDocumentsByCreator(String creatorUsername, Integer spaceId) {
        return documentMapper.searchDocumentsByCreator(creatorUsername, spaceId);
    }

    /**
     * 根据文档类型搜索
     */
    public List<Document> searchDocumentsByType(String documentType, Integer spaceId) {
        return documentMapper.searchDocumentsByType(documentType, spaceId);
    }

    /**
     * 根据文件夹ID获取文档列表
     */
    public List<Document> getDocumentsByFolderId(Integer folderId) {
        return documentMapper.getDocumentsByFolderId(folderId);
    }

    /**
     * 高级搜索文档
     */
    public List<Document> advancedSearchDocuments(String keyword, Integer spaceId, String creatorUsername,
            String documentType, Integer folderId, String startDate, String endDate) {
        return documentMapper.advancedSearchDocuments(keyword, spaceId, creatorUsername, documentType, folderId,
                startDate, endDate);
    }

    /**
     * 智能搜索建议
     */
    public List<String> getSearchSuggestions(String keyword, Integer spaceId) {
        // 这里可以实现搜索建议逻辑
        // 例如：根据历史搜索、热门搜索等提供建议
        List<String> suggestions = new java.util.ArrayList<>();

        if (keyword != null && !keyword.trim().isEmpty()) {
            // 简单的建议实现：基于现有文档标题
            List<Document> documents = searchDocumentsByTitle(keyword, spaceId);
            for (Document doc : documents) {
                if (suggestions.size() >= 5)
                    break; // 最多返回5个建议
                if (!suggestions.contains(doc.getDocumentName())) {
                    suggestions.add(doc.getDocumentName());
                }
            }
        }

        return suggestions;
    }

    /**
     * 获取文档文件内容（二进制格式）
     */
    public byte[] getDocumentFileContent(Integer documentId) throws IOException {
        Document document = getDocumentById(documentId);
        if (document == null) {
            throw new IOException("文档不存在");
        }

        if ("filesystem".equals(document.getStorageType()) && document.getFilePath() != null) {
            // 从文件系统读取
            Path fullPath = Paths.get(uploadPath, document.getFilePath());
            if (!Files.exists(fullPath)) {
                throw new IOException("文件不存在: " + fullPath.toString());
            }
            return Files.readAllBytes(fullPath);
        } else if ("database".equals(document.getStorageType()) && document.getContent() != null) {
            // 从数据库读取（文本内容转为字节）
            return document.getContent().getBytes(StandardCharsets.UTF_8);
        } else {
            throw new IOException("无法获取文档内容");
        }
    }

    /**
     * 读取文件系统中的文件内容
     */
    private String readFileContent(String filePath) throws IOException {
        // 构建完整的文件路径
        Path fullPath = Paths.get(uploadPath, filePath);

        // 检查文件是否存在
        if (!Files.exists(fullPath)) {
            throw new IOException("文件不存在: " + fullPath.toString());
        }

        // 读取文件内容
        byte[] bytes = Files.readAllBytes(fullPath);
        return new String(bytes, "UTF-8");
    }

    /**
     * 删除文件系统中的文件
     */
    private void deleteFileFromSystem(String filePath) {
        try {
            String fullPath = uploadPath + "/" + filePath;
            File file = new File(fullPath);
            if (file.exists()) {
                boolean deleted = file.delete();
                if (deleted) {
                    System.out.println("文件删除成功: " + fullPath);
                } else {
                    System.err.println("文件删除失败: " + fullPath);
                }
            } else {
                System.out.println("文件不存在: " + fullPath);
            }
        } catch (Exception e) {
            System.err.println("删除文件时发生错误: " + e.getMessage());
            e.printStackTrace();
        }
    }
}
